home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
buildGraphs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
6KB
|
236 lines
/*
* @(#)buildGraphs.c 1.3 6/29/87
*/
#include "assert.h"
#include "nodes.h"
#include "map.h"
#include "sequence.h"
#include "trace.h"
Map symbolsRead;
Map symbolsWritten;
void addAnEdge(map, symref, expression)
Map map;
NodePtr symref, expression;
{
NodePtr list;
if (symref->b.symref.symbol == NULL) assert(FALSE);
list = (NodePtr) Map_Lookup(map, (int)symref->b.symref.symbol);
if ((int)list == NIL) list = NULL;
Sequence_Add(&list, expression);
Map_Insert(map, (int)symref->b.symref.symbol, (int)list);
}
static Boolean duplicatesSymbol(p, st)
NodePtr p;
Symbol st;
{
NodePtr q;
switch (p->tag) {
case P_INVOC:
Sequence_For(q, p->b.invoc.args)
assert(q->tag == P_ARG);
q = q->b.arg.exp;
if (q->tag == P_SYMREF && q->b.symref.symbol == st) {
TRACE2(graph, 1, "reference to %s on line %d is as arg, so duplicates",
ST_SymbolName(st), p->lineNumber);
return(TRUE);
}
Sequence_Next
TRACE2(graph, 1, "Invocation on %s on line %d does not duplicate",
ST_SymbolName(st), p->lineNumber);
break;
case P_ASSIGNSTAT:
Sequence_For(q, p->b.assignstat.right)
if (q->tag == P_SYMREF && q->b.symref.symbol == st) {
TRACE2(graph, 1, "reference to %s on line %d is as expression, so duplicates",
ST_SymbolName(st), p->lineNumber);
return(TRUE);
}
Sequence_Next
TRACE2(graph, 1, "Assignment to %s on line %d does not duplicate",
ST_SymbolName(st), p->lineNumber);
break;
case P_ATLIT:
case P_OBLIT:
TRACE2(graph, 1, "reference to %s on line %d is as import, so duplicates",
ST_SymbolName(st), p->lineNumber);
return(TRUE);
/* break; */
default:
break;
}
return(FALSE);
}
void buildSymbolGraph(p)
register NodePtr p;
{
register NodePtr q, list;
Boolean duplicatesSelf;
register Symbol st;
if ((int)p <= 0x200) return;
switch (p->tag) {
case P_ASSIGNSTAT:
Sequence_For(q, p->b.assignstat.left)
assert(q->tag == P_SYMREF);
addAnEdge(symbolsWritten, q, p);
Sequence_Next
Sequence_For(q, p->b.assignstat.right)
if (q->tag == P_SYMREF) addAnEdge(symbolsRead, q, p);
Sequence_Next
break;
case P_INVOC:
if (p->b.invoc.target->tag == P_SYMREF)
addAnEdge(symbolsRead, p->b.invoc.target, p);
Sequence_For(q, p->b.invoc.args)
assert(q->tag == P_ARG);
q = q->b.arg.exp;
if (q->tag == P_SYMREF)
addAnEdge(symbolsRead, q, p);
Sequence_Next
break;
case P_CONSTDECL:
case P_VARDECL:
if (p->b.constdecl.value != NN)
addAnEdge(symbolsWritten, p->b.constdecl.sym, p);
break;
case P_PARAM:
if (p->b.param.sym->b.symdef.symbol->itsKind == ST_Param)
addAnEdge(symbolsWritten, p->b.param.sym, p);
break;
case P_UNARYEXP:
if (p->b.unaryexp.exp->tag == P_SYMREF)
addAnEdge(symbolsWritten, p->b.unaryexp.exp, p);
break;
case P_EXP:
if (p->b.exp.left->tag == P_SYMREF)
addAnEdge(symbolsWritten, p->b.exp.left, p);
if (p->b.exp.right->tag == P_SYMREF)
addAnEdge(symbolsWritten, p->b.exp.right, p);
break;
case P_ATLIT:
case P_OBLIT:
Sequence_For(q, p->b.oblit.setq)
if (q->b.setq.outer->tag == P_SYMREF) {
addAnEdge(symbolsRead, q->b.setq.outer, p);
}
assert(q->b.setq.inner->tag == P_SYMDEF);
addAnEdge(symbolsWritten, q->b.setq.inner, p);
Sequence_Next
addAnEdge(symbolsWritten, p->b.atlit.name, p);
break;
case P_IMPORT:
Sequence_For(q, p->b.import.syms)
addAnEdge(symbolsWritten, q, p);
Sequence_Next
break;
case P_EXPORT:
if (p->b.export.path == NN) break;
Sequence_For(q, p->b.export.syms)
addAnEdge(symbolsWritten, q, p);
Sequence_Next
break;
default:
break;
}
Sequence_For(q, p)
if ((int)q > 0x200) buildSymbolGraph(q);
Sequence_Next
switch (p->tag) {
case P_OBLIT:
st = p->b.oblit.name->b.symdef.symbol;
list = (NodePtr) Map_Lookup(symbolsRead, (int)st);
if ((int)list == NIL) list = NULL;
duplicatesSelf = FALSE;
Sequence_For(q, list)
if (duplicatesSymbol(q, st)) duplicatesSelf = TRUE;
Sequence_Next
p->b.oblit.f.doesNotDuplicateSelf = !duplicatesSelf;
break;
case P_ATLIT:
p->b.atlit.f.doesNotDuplicateSelf = TRUE;
break;
default:
break;
}
}
void initializeGraphs()
{
symbolsRead = Map_Create();
symbolsWritten = Map_Create();
}
static void findSingleReferences()
{
Symbol st;
NodePtr list, q;
Boolean duplicates;
Map_For(symbolsWritten, st, list)
if (Sequence_Length(list) == 0) {
TRACE1(graph, 1, "Symbol %s is never written", ST_SymbolName(st));
} else if (Sequence_Length(list) == 1) {
TRACE1(graph, 1, "Symbol %s is written only once", ST_SymbolName(st));
list = (NodePtr) Map_Lookup(symbolsRead, (int)st);
if (list == (NodePtr)NIL) list = NULL;
duplicates = FALSE;
Sequence_For(q, list)
if (duplicatesSymbol(q, st)) duplicates = TRUE;
Sequence_Next
if (!duplicates) {
TRACE1(graph, 1, "Symbol %s is single reference", ST_SymbolName(st));
st->isSingleReference = TRUE;
} else {
TRACE1(graph, 1, "Symbol %s is not single reference", ST_SymbolName(st));
}
} else {
TRACE2(graph, 1, "Symbol %s is written %d times", ST_SymbolName(st),
Sequence_Length(list));
}
Map_Next
}
void displaySymbolGraph()
{
Symbol st;
NodePtr list, q;
IFTRACE(graph, 3) {
Map_For(symbolsRead, st, list)
printf("Symbol %s is read:\n", ST_SymbolName(st));
Sequence_For(q, list)
printf("\t\tin %s on line %d\n", tagNames[(int)q->tag], q->lineNumber);
Sequence_Next
list = (NodePtr) Map_Lookup(symbolsWritten, (int)st);
if ((int)list != NIL) {
printf("\tand written:\n");
Sequence_For(q, list)
printf("\t\tin %s on line %d\n", tagNames[(int)q->tag], q->lineNumber);
Sequence_Next
} else {
printf("\tbut never written\n");
}
Map_Next
Map_For(symbolsWritten, st, list)
if (Map_Lookup(symbolsRead, (int)st) == NIL) {
printf("Symbol %s is only written:\n", ST_SymbolName(st));
Sequence_For(q, list)
printf("\t\tin %s on line %d\n", tagNames[(int)q->tag], q->lineNumber);
Sequence_Next
}
Map_Next
}
}
void doSymbolGraph(p)
NodePtr p;
{
buildSymbolGraph(p);
findSingleReferences();
displaySymbolGraph();
}